﻿
using EasyPhysic.Collider;
using NativeTrees;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;


namespace EasyPhysic.Job
{
    public struct UpdatePhysicGroupColliderJob : IJobParallelFor
    {
        /// <summary>
        /// 进行检查的对象
        /// </summary>
        public NativeArray<ColliderBody> check;
        /// <summary>
        /// 被检查的对象
        /// </summary>
        public NativeArray<ColliderBody> colliderBodyList;
        
        /// <summary>
        /// 检查的结果
        /// </summary>
        
        NativeQuadtree<int> quadtree;
        
        // public NativeArray<Vector2> _normals;
        // public NativeArray<Vector2> _subNormals;
        public void Execute(int index)
        {
            var info=check[index];
            
        }
        
        
        
        
        /// <summary>
        /// 获得目标点,目前该接口不支持返回目标点
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ls"></param>
        /// <returns></returns>
        public void ReadTargetId(ColliderBody info,ref NativeList<int> ls)
        {

            if (Mathf.Approximately(info.Center.x, default))
            {
                return;
            }
            var results=new UnsafeParallelHashSet<int>();
            // 1.多线程 
            // 2.四叉树 √
            quadtree.RangeAABBUnique(info.Bound,results);
        
            //在目标组中获得
            // for (int i = 0; i < info.TargetGroups.Length; i++)
            // {
            //     var groupId=info.TargetGroups[i];
            //     var group=_physicGroups[groupId];
            //     group.ReadTargetId(info,ref results);
            // }
            
            
          
            // 三个阶段
          
            
            // 粗略检查,四叉树查询
            // 精准,包围盒检查
            // 详细检查
            // foreach (var targetId in results)
            // {
            //     if (!targets.ContainsKey(targetId))
            //     {
            //         continue;
            //     }
            //     var target = targets[targetId];
            //    
            //     if (target.IsValid)
            //     {
            //         // 采用包围盒检查
            //         if(!info.Bound.Overlaps(target.ShapeInfo.Bound))
            //         {
            //             // 如果不在包围盒中
            //             continue;
            //         }
            //         // 
            //         if (OverlapCollider(info, target.ShapeInfo))
            //         {
            //             ls.Add(target.SerialId);
            //         }
            //     }
            // }
          
        }
        
        /// <summary>
        /// 重叠检查,检查两个单位是否相加
        /// </summary>
        /// <param name="collider1"></param>
        /// <param name="collider2"></param>
        public bool OverlapCollider(ColliderBody collider1,ColliderBody collider2)
        {
            switch (collider1.ColliderShapeType)
            {
                case ColliderShapeType.Circle:
                    if (collider2.ColliderShapeType == ColliderShapeType.Circle)
                    {
                        return CheckCircleAndCircle(collider1,collider2);
                    }
                    else
                    {
                        return CheckCircleAndPolygon(collider1,collider2);
                    }
                default:
                    if (collider2.ColliderShapeType == ColliderShapeType.Circle)
                    {
                        
                        return CheckCircleAndPolygon(collider2,collider1);
                    }
                    else
                    {
                        return CheckPolygonAndPolygon(collider2,collider1);
                    }
            }
            // return true;
        }
        
        /// <summary>
        /// 圆形和多边形的碰撞检测
        /// </summary>
        /// <returns></returns>
        bool CheckCircleAndPolygon(ColliderBody circleCollider,ColliderBody polygonCollider)
        {
            
            // return false;
            // 如果多边形任意一点在圆形中,相交
            // 另外一种情况是圆形被多边形包围，此时任一一点也不会与圆形相交。
            if (!(circleCollider.ColliderShapeType == ColliderShapeType.Circle &&
                 polygonCollider.ColliderShapeType != ColliderShapeType.Circle))
            {
                Debug.LogError("collider is invalid");
                return false;
            }
        
            // 如果任意一个顶点在点在圆中，相交
            for (int i = 0; i < polygonCollider.Vertexs.Length; i++)
            {
                var vertex = polygonCollider.Vertexs[i];
                if (Vector3.Distance(vertex+polygonCollider.Center, circleCollider.Center) <= circleCollider.Radius)
                {
                    return true;
                }
                
            }
            
            // 判断圆心是否在多边形中
        
            if (CheckPointInPolygon(polygonCollider.Vertexs, polygonCollider.Center, circleCollider.Center))
            {
                return true;
            }
        
            //检查多边形的边是否与圆相交
            for (int i = 0; i < polygonCollider.Vertexs.Length; i++)
            {
                var pointA=polygonCollider.Vertexs[i]+polygonCollider.Center;
                var pointB=polygonCollider.Vertexs[(i + 1) % polygonCollider.Vertexs.Length]+polygonCollider.Center;
                if (CheckCircleAndEdge(circleCollider.Center, circleCollider.Radius, pointA, pointB))
                {
                    return true;
                }   
            }
            return false;
            
        }
        
        
        /// <summary>
        /// 圆形和边的碰撞检测
        /// </summary>
        /// <param name="circleCenter">圆心</param>
        /// <param name="circleRange">圆半径</param>
        /// <param name="edgePointA"></param>
        /// <param name="edgePointB"></param>
        /// <returns></returns>
        bool CheckCircleAndEdge(Vector2 circleCenter,float circleRange,Vector2 edgePointA,Vector2 edgePointB)
        {
            
            Vector2 AB = edgePointB - edgePointA;
            Vector2 AP = circleCenter - edgePointA;
            float t = Mathf.Clamp01(Vector2.Dot(AP, AB) / AB.sqrMagnitude); // 投影参数 t ∈ [0, 1]
            Vector2 H = edgePointA+ t * AB; // 垂足点
            return Vector2.Distance(circleCenter, H) < circleRange;
        }
        
        /// <summary>
        /// 检查点是否在多边形中
        /// </summary>
        /// <param name="polygonPoints"></param>
        /// <param name="polygonOffset"></param>
        /// <param name="pointCenter"></param>
        /// <returns></returns>
        bool CheckPointInPolygon(UnsafeList<Vector2> polygonPoints,Vector2 polygonOffset, Vector2 pointCenter )
        {
            int tag = 0;
            var lastPoint=polygonPoints[0]+polygonOffset;
            var thisPoint = Vector2.zero;
            var v1=Vector2.zero;
            var v2 = Vector2.zero;
            int direct = 0;
            for (int i = 1; i < polygonPoints.Length; i++)
            {
                thisPoint=polygonPoints[i]+polygonOffset;
                v1=pointCenter-lastPoint;
                v2 = thisPoint - lastPoint;
                // 指的方向
                direct= Vector3.Cross(v1, v2).z>0?1:-1;
                lastPoint = thisPoint;
                if (tag == 0)
                {
                    tag = direct;
                }
                else
                {
                    // 不在同向，则表示在外部
                    if (tag != direct)
                    {
                        return false;
                    }
                }
            }
            
            // 计算最后一个点
            thisPoint=polygonPoints[0]+polygonOffset;
            v1=pointCenter-lastPoint;
            v2 = thisPoint - lastPoint;
            // 如果
            int  d= Vector3.Cross(v1, v2).z>0?1:-1;
            // 两个点在两边上，所以正好是在内部
            if (tag != d)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 圆形和圆形的碰撞检测
        /// </summary>
        /// <returns></returns>
        bool CheckCircleAndCircle(ColliderBody collider1,ColliderBody collider2)
        {
            // 判断两个圆心的距离是否小于等于半径之和
            if (!(collider2.ColliderShapeType == ColliderShapeType.Circle &&
                  collider2.ColliderShapeType == ColliderShapeType.Circle))
            {
                Debug.LogError("collider is invalid");
                return false;
            }
            return Vector2.Distance(collider1.Center,collider2.Center)<=collider1.Radius+collider2.Radius;
        }
        
        
        /// <summary>
        /// 多边形和多边形的碰撞检测
        /// </summary>
        /// <returns></returns>
        bool CheckPolygonAndPolygon(ColliderBody collider1,ColliderBody collider2)
        {
            if (!(collider2.ColliderShapeType != ColliderShapeType.Circle &&
                 collider2.ColliderShapeType != ColliderShapeType.Circle))
            {
                Debug.LogError("collider is invalid");
                return false;
            }
           
            var _normals = new NativeList<Vector2>(collider1.Vertexs.Length + collider2.Vertexs.Length, Allocator.Temp);
            
            _normals.AddRange(GetNormal(collider1.Vertexs,collider1.Center));
            _normals.AddRange(GetNormal(collider2.Vertexs,collider2.Center));
            // 计算每一条法向量上是否相交.有一条相交，是
            for (int i = 0; i < _normals.Length; i++)
            {
                var normal=_normals[i];
                var node1=GetNormalLength(normal,collider1.Vertexs,collider1.Center);
                var node2=GetNormalLength(normal,collider2.Vertexs,collider2.Center);
                if (node1.Item1 > node2.Item2 || node1.Item2 < node2.Item1)
                {
                    return false;
                }
            }
            return true;
        }
        
        // GetPointsMaxLengthJob _getPointsMaxLengthJob=new GetPointsMaxLengthJob();
        
        
        
        (float, float) GetNormalLength(Vector2 normal,UnsafeList<Vector2>  points,Vector2 offset)
        {
            float max = float.MinValue;
            float min = float.MaxValue;
            for (int i = 0; i < points.Length; i++)
            {
                var point = points[i];
                var dot = Vector2.Dot(point+offset, normal);
                if (dot > max)
                {
                    max = dot;
                }
                if (dot < min)
                {
                    min = dot;
                }
            }
            return (min, max);
        }
        
        /// <summary>
        /// 获得法向量
        /// </summary>
        /// <param name="points"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        NativeList<Vector2> GetNormal(UnsafeList<Vector2> points,Vector2 offset)
        {
           var _subNormals = new NativeList<Vector2>(points.Length, Allocator.Temp);
            Vector2 start=points[0]+offset;
            Vector2 edge=Vector2.zero;
            for (int i = 1; i < points.Length; i++)
            {
                edge = start - points[i] + offset;
                _subNormals.Add(ToNormal(edge));
                start = points[i]+offset;
            }
            _subNormals.Add(ToNormal(points[0]+offset-start));
            return _subNormals;
        }
        [BurstCompile]
        Vector2 ToNormal(Vector2 v)
        {
            return new Vector2(-v.y, v.x);
        }
    }
}